/*************************************************************************
	> File Name: VoltageLimiter.c
	> Author: 
	> Mail: 
	> Created Time: 2018/1/23 Tue 10:16
	> Version     :
 ************************************************************************/

#include<stdio.h>

#include "BaseAlgo.h"
#include "VoltageLimiter.h"

/***********************************************************************************************
 * *Name        :volLimiterDecimateProcess
 * *Description :Data Decimate Process,get max value form echo decimate_number data
 * *Parameter   :inData ,decimate configuration
 * *Return Value: effective data number after decimate
 * *Version: v1.0.0
 * ********************************************************************************************/
static uint16_t volLimiterDecimateProcess(int32_t *data,uint16_t dataCnt,uint16_t enable)
{
    int i,j,decDataCnt;
    uint16_t ret = dataCnt;

    if(VOL_DEC_ENABLE != (enable&VOL_DEC_ENABLE_MASK))
        return ret;

    //convert to absolute interger
    for(i=0;i<dataCnt;i++)
    {
        data[i] = absoluteInt32(data[i]);
    }

    if(dataCnt%VOL_DEC_NUMBER == 0)
    {
        decDataCnt = dataCnt/VOL_DEC_NUMBER;
        for(i=0;i<decDataCnt;i++)
        {
            data[i] = data[i*VOL_DEC_NUMBER];
            for(j=0;j<VOL_DEC_NUMBER;j++)
            {
                data[i] = GetMaxValue(data[i],data[i*VOL_DEC_NUMBER + j]);
            }
        }
        ret = decDataCnt;
    }else{
        decDataCnt = dataCnt/VOL_DEC_NUMBER;
        for(i=0;i<decDataCnt;i++)
        {
            data[i] = data[i*VOL_DEC_NUMBER];
            for(j=0;j<VOL_DEC_NUMBER;j++)
            {
                data[i] = GetMaxValue(data[i],data[i*VOL_DEC_NUMBER + j]);
            }
        }
        j = dataCnt - decDataCnt*VOL_DEC_NUMBER;
        data[decDataCnt] = data[decDataCnt*VOL_DEC_NUMBER];
        for(i=0;i<j;i++)
        {
            data[decDataCnt] = GetMaxValue(data[decDataCnt],data[decDataCnt*VOL_DEC_NUMBER + i]);
        }
        ret = decDataCnt + 1;
    }

    return decDataCnt;
}
/***********************************************************************************************
 * *Name        :volUndecimateProcess
 * *Description :Data UnDecimate Process , return to original data
 * *Parameter   :inData ,inputdata number ,outData number
 * *Return Value: NULL
 * *Version: v1.0.0
 * ********************************************************************************************/
static void volUndecimateProcess(int32_t *data,uint16_t inDataCnt,uint16_t outDataCnt)
{
    uint16_t i,j;
    uint16_t count;
    int32_t *outData,*inData;

    if(inDataCnt == outDataCnt)
        return;

    inData = data + (outDataCnt - inDataCnt);

    //move orgin data to buffer tail
    for(i=0;i<inDataCnt;i++)
    {
        inData[i] = data[i];
    }

    outData = data;

    if(outDataCnt%inDataCnt ==0)
    {
        for(i=0;i<inDataCnt;i++)
        {
            for(j=0;j<VOL_DEC_NUMBER;j++)
            {
                outData[i*VOL_DEC_NUMBER+j] = inData[i];
            }
        }
    }else{
        count = outDataCnt/VOL_DEC_NUMBER;
        for(i=0;i<count;i++)
        {
            for(j=0;j<VOL_DEC_NUMBER;j++)
            {
                outData[i*VOL_DEC_NUMBER + j] = inData[i];
            }
        }
        j = outDataCnt - count*VOL_DEC_NUMBER;
        for(i=0;i<j;i++)
        {
            outData[count*VOL_DEC_NUMBER+i]= inData[count];
        }
    }
}
/***********************************************************************************************
 * *Name        :volLimiterProcess
 * *Description :Voltage Limiter process
 * *Parameter   :inData ,voltage Configuration structure  ,inData number
 * *Return Value: NULL
 * *Version: v1.0.0
 * ********************************************************************************************/
void volLimiterProcess(int32_t *data,volLimiterCfg_t *cfg,uint16_t dataCnt)
{
    uint16_t decDataCnt = dataCnt;

    //decimate process
    decDataCnt = volLimiterDecimateProcess(data,dataCnt,cfg->moduleEnable);
    //write_pcm("../data/volDec.pcm",data,decDataCnt);
    //get peak value process
    peakDetectorProcess(data,&cfg->pd_cfg,decDataCnt);
    //write_pcm("../data/volpeakDet.pcm",data,decDataCnt);
    //data curve process
    curveProcess(data,&cfg->gcur_cfg,decDataCnt);
    //write_pcm("../data/volcurve.pcm",data,decDataCnt);
    //data smooth process
    smoothProcess(data,&cfg->gs_cfg,decDataCnt);
    //write_pcm("../data/volsmooth.pcm",data,decDataCnt);

    //undecimate process
    volUndecimateProcess(data,decDataCnt,dataCnt);
    //write_pcm("../data/volUndec.pcm",data,dataCnt);
}

int voltageLimiterInit(volLimiterCfg_t *cfg)
{
    peakDetectorInit(&cfg->pd_cfg);
    curveInit(&cfg->gcur_cfg);
    smoothInit(&cfg->gs_cfg);
    return 0;
}

int voltageLimiterReset(volLimiterCfg_t *cfg)
{
    peakDetectorReset(&cfg->pd_cfg);
    curveReset(&cfg->gcur_cfg);
    smoothReset(&cfg->gs_cfg);
    return 0;
}

int voltageLimiterSetParams(volLimiterCfg_t *cfg,volLimiterParams_t *params,int32_t threshold)
{
    peakDetSetParams(&cfg->pd_cfg,&params->pd_params);
    curveSetParams(&cfg->gcur_cfg,&params->gcur_params,threshold);
    smoothSetParams(&cfg->gs_cfg,&params->gs_params);
    return 0;
}
int voltageLimiterGetParams(volLimiterCfg_t *cfg,volLimiterParams_t *params,int32_t *threshold)
{
    peakDetGetParams(&cfg->pd_cfg,&params->pd_params);
    curveGetParams(&cfg->gcur_cfg,&params->gcur_params,threshold);
    smoothGetParams(&cfg->gs_cfg,&params->gs_params);
    return 0;
}
